도구를 활용한 다중 턴 대화

Anthropic
Claude에서 열기
이 강좌에 대해 질문하기
노트 복사
LLM용 전체 강좌 노트 복사

여러 도구를 사용하는 애플리케이션을 개발할 때, Claude가 단일 사용자 질문에 답하기 위해 여러 도구를 순서대로 호출해야 하는 시나리오를 처리해야 합니다. 예를 들어, 사용자가 "오늘부터 103일 후는 무슨 요일인가요?"라고 묻는다면, Claude는 먼저 현재 날짜를 가져온 후 103일을 더해야 합니다.

이로 인해 Claude가 최종 답변을 제공하기 전에 여러 번 도구를 요청하는 다중 턴 대화 패턴이 생성됩니다. 애플리케이션은 이를 자동으로 처리해야 합니다.

다중 턴 도구 패턴

Claude가 여러 도구를 필요로 할 때 내부적으로 일어나는 과정은 다음과 같습니다:

  1. 사용자가 묻습니다: "오늘부터 103일 후는 무슨 요일인가요?"
  2. Claude가 get_current_datetime을 요청하는 도구 사용 블록으로 응답합니다
  3. 서버가 함수를 호출하고 결과를 반환합니다
  4. Claude가 추가 정보가 필요함을 인식하고 add_duration_to_datetime을 요청합니다
  5. 서버가 해당 함수를 호출하고 결과를 반환합니다
  6. Claude가 이제 최종 답변을 제공하기에 충분한 정보를 보유합니다

대화 루프 구축

이 패턴을 처리하려면 Claude가 도구 요청을 멈출 때까지 계속되는 대화 루프가 필요합니다:

def run_conversation(messages):
    while True:
        response = chat(messages)
        
        add_user_message(messages, response)
        
        # Pseudo code
        if response isn't asking for a tool:
            break
            
        tool_result_blocks = run_tools(response)
        add_user_message(tool_result_blocks)
        
    return messages

헬퍼 함수 리팩토링

대화 루프를 구현하기 전에, 여러 메시지 블록을 올바르게 처리할 수 있도록 헬퍼 함수를 업데이트해야 합니다.

메시지 핸들러 업데이트

현재 add_user_messageadd_assistant_message 함수는 항상 일반 텍스트로 작업한다고 가정합니다. 전체 메시지 객체를 처리할 수 있도록 업데이트하세요:

from anthropic.types import Message

def add_user_message(messages, message):
    user_message = {
        "role": "user",
        "content": message.content if isinstance(message, Message) else message
    }
    messages.append(user_message)

이를 통해 문자열, 블록 목록, 또는 완전한 메시지 객체를 전달할 수 있습니다.

채팅 함수 업데이트

채팅 함수가 도구 목록을 받아들이고 텍스트만이 아닌 전체 메시지를 반환하도록 수정하세요:

def chat(messages, system=None, temperature=1.0, stop_sequences=[], tools=None):
    params = {
        "model": model,
        "max_tokens": 1000,
        "messages": messages,
        "temperature": temperature,
        "stop_sequences": stop_sequences,
    }
    
    if tools:
        params["tools"] = tools
        
    if system:
        params["system"] = system
        
    message = client.messages.create(**params)
    return message

메시지에서 텍스트 추출

이제 전체 메시지 객체를 반환하므로, 필요할 때 텍스트를 추출하는 헬퍼를 만드세요:

def text_from_message(message):
    return "\n".join(
        [block.text for block in message.content if block.type == "text"]
    )

이 함수는 메시지의 모든 텍스트 블록을 찾아 하나로 합칩니다. 사용자에게 최종 응답을 표시해야 할 때 유용합니다.

주요 개선 사항

이 리팩토링 단계들은 견고한 도구 처리를 위해 코드를 준비합니다:

  • 유연한 메시지 처리 - 헬퍼 함수가 이제 다양한 메시지 형식으로 작동할 수 있습니다
  • 채팅에서의 도구 지원 - 채팅 함수가 도구 스키마를 받아서 전달할 수 있습니다
  • 전체 메시지 반환 - 텍스트만이 아닌 완전한 메시지 객체를 얻어 모든 블록이 보존됩니다
  • 텍스트 추출 유틸리티 - 복잡한 메시지에서 읽기 쉬운 텍스트를 얻는 간편한 방법

이러한 기반이 갖춰지면, 여러 도구 호출을 자동으로 처리하는 대화 루프를 구현할 준비가 됩니다. 이를 통해 Claude가 사용자 질문에 답하기 위해 필요한 만큼 도구를 사용할 수 있는 원활한 경험을 만들 수 있습니다.

다운로드